#include "CLongScreenShot.h"
#include <QDebug>
#include <QGuiApplication>
#include <QQuickItem>
#include <QMetaObject>
#include <QQmlContext>
#include <QQmlApplicationEngine>
#include <QWindow>
#include <QScreen>
#include "CImageAlgorithm.h"
#include <QMouseEvent>
#include <QDir>
#include <QTest>
#include <QWheelEvent>
#include <QTimer>
#include <QFileInfoList>

CLongScreenShot::CLongScreenShot(QQmlEngine *engine, QObject *parent)
    : QObject{parent},m_pEngine{engine}
{
//    qApp->installEventFilter(this);
}

bool CLongScreenShot::start(QObject *object)
{
    qInfo() << Q_FUNC_INFO << object;

    QWindow *pWindow = qobject_cast<QWindow *>(object);

    if (!pWindow) {
        qWarning() << "Is not QWindow:" << object;
        return false;
    }

    if (!m_pEngine) {
        qWarning() << "Engine nullptr:" << m_pEngine;
        return false;
    }

    //1.截图找到行像素相同的的最大数 sameMaxRowCnt
    QPixmap pixmap = pWindow->screen()->grabWindow();

    int nSameMaxRows = sameMaxRowCnt(pixmap);
    qDebug() << "nSameMaxRows:" << nSameMaxRows;

    //2.让 Window 滚动1像素，截图存到指定目录。循环 sameMaxRowCnt 次。根据这些截图找到 title, scrollArea, appBar的两条分界线。
    QRect rectScrollArea = findScrollArea(pWindow, nSameMaxRows);
    qDebug() << "rectScrollArea.x:" << rectScrollArea.x() << " rectScrollArea.height:" << rectScrollArea.height();

    //3.从 appBar.x，每次滚动 scrollArea.height,截图。直至到底部（触发结束）或到 SingleCaptureHeight （自动缓存一次的图片高度，需要用户继续滚动才会接着截图。）

    return true;
}

void CLongScreenShot::mousePress(QWindow *window, int x, int y)
{

//    #define MOUSE_EVENT(type,x,y,gX,gY) QMouseEvent(type, QPointF(x,y), QPointF(gX,gY),Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)

//        QGuiApplication::sendEvent(window, new MOUSE_EVENT(QEvent::MouseButtonPress,123,192,923,468));
//        QGuiApplication::sendEvent(window, new MOUSE_EVENT(QEvent::MouseMove,123,182,923,458));
//        QGuiApplication::sendEvent(window, new MOUSE_EVENT(QEvent::MouseMove,123,172,923,448));
//        QGuiApplication::sendEvent(window, new MOUSE_EVENT(QEvent::MouseButtonRelease,123,162,923,438));

//    #undef MOUSE_EVENT
    QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(x, y));
}

void CLongScreenShot::mouseMove(QWindow *window, int x, int y)
{
    QTest::mouseMove(window,  QPoint(x, y));
}

void CLongScreenShot::mouseRelease(QWindow *window, int x, int y)
{
    QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier,  QPoint(x, y));
}

QList<QQuickWindow *> CLongScreenShot::findWindw(QQmlEngine *engine)
{
    QList<QQuickWindow *> listWindow;

    //1.尝试转换为 QQmlApplicationEngine
    QQmlApplicationEngine *pAppEngine = qobject_cast<QQmlApplicationEngine *>(m_pEngine);
    if (pAppEngine) {
        qDebug() << "rootObj:" << pAppEngine->rootObjects();
        foreach (QObject *obj, pAppEngine->rootObjects()) {
            if (obj->inherits("QQuickWindow")) {
                QQuickWindow *pWindow = qobject_cast<QQuickWindow *>(obj);
                if (pWindow)
                    listWindow.append(pWindow);
            }
        }
    } else {
        if (engine->parent()->inherits("QQuickWindow")) {
            QQuickWindow *pWindow = qobject_cast<QQuickWindow *>(engine->parent());
            if (pWindow)
                listWindow.append(pWindow);
        }
    }

    return listWindow;
}

bool CLongScreenShot::eventFilter(QObject *obj, QEvent *event)
{
    QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent *>(event);
    if (obj->metaObject()->className() == QString("QQuickFlickable"))
//        if (mouseEvent)
    qDebug() << "Event:" << obj << event->type() << event;

    // 在这里进行事件过滤和处理

    // 如果要继续传递事件给应用程序，请返回 false
    // 如果要停止传递事件，请返回 true


    return false;
}

int CLongScreenShot::sameMaxRowCnt(QPixmap &pixmap)
{
    return CImageAlgorithm::findMaxConsecutiveRows(pixmap);
}

QRect CLongScreenShot::findScrollArea(QWindow *target, int scrollHeight)
{
    QRect rectScrollArea;
    QString findArePath = "./findArea";
    //1.检查目录  不存在就创建
    QDir dir(findArePath);
    if (!dir.exists()) {
        if (dir.mkpath(".")) {
            qInfo() << "Directory created:" << findArePath;
        } else {
            qWarning() << "Failed to create directory:" << findArePath;
        }
    } else {
        qInfo() << "Directory already exists:" << findArePath;
    }




    //2.创建截图
    QPointF ptWindowCenter(target->width() / 2,target->height() / 2);
    //    for (int i = 0; i < scrollHeight; i++) {
    QPointF ptEnd(ptWindowCenter.x(), ptWindowCenter.y() - 10);
    scrollWindow(target, ptWindowCenter, ptEnd);
    ////        QImage imageWindow = grabWindow(target);
    ////        QString fileName = QString("%1/%2-find-scrollArea.png").arg(findArePath).arg(i, 4, 10, QLatin1Char('0'));
    ////        bool ok = imageWindow.save(fileName, "PNG");
    ////        if (!ok) {
    ////            qWarning() << " Save failed:" << fileName;
    ////        } else {
    ////            qDebug() << "Save:" << fileName;
    ////        }
    //    }

    qDebug() << "FindScrollArea...";
    QList<QQuickItem *> listItems = target->findChildren<QQuickItem *>(); //像 QQuickFlickable 是Qt私有类，所以不能直接查找
//    qDebug() << "listItems:" << listItems;
    QStringList scrollAreaClassNames;
    scrollAreaClassNames << "QQuickFlickable" << "QQuickListView" << "QQuickGridView";
    QQuickItem *pCurrentScrollAreaItem = nullptr;
    foreach (QQuickItem *pItem, listItems) {
        if (scrollAreaClassNames.contains(pItem->metaObject()->className())) {
            qDebug() << pItem->objectName() << pItem->metaObject()->className() << " " << pItem->isVisible()
                     << pItem->x() << pItem->y() << pItem->mapToScene(QPointF(0,0)) << pItem->property("");
            QPointF ptPosition = pItem->mapToScene(QPointF(0,0));
            int contentHeight = pItem->property("contentHeight").toInt();
            if ((ptPosition.x() >= 0 && ptPosition.x() < (target->width() * 0.5))
                && pItem->height() < contentHeight) {
                qInfo() << "FindListView:" << pItem << pItem->objectName();
                pCurrentScrollAreaItem = pItem;
                break ;
            }
        }
    }

    if (nullptr == pCurrentScrollAreaItem) {
        qWarning() << "Window no scorll area item:" << scrollAreaClassNames;
        return QRect();
    }

    if (!pCurrentScrollAreaItem->property("contentY").isValid()) {
        qWarning() << "Window no scorll area item:" << scrollAreaClassNames;
        return QRect();
    }

    for(int i = 0; i < scrollHeight; i++) {
        //滚动1像素
        QVariant varContentY = pCurrentScrollAreaItem->property("contentY");
        qDebug() << "varContentY:" << varContentY;
        if (varContentY.isValid() && pCurrentScrollAreaItem->property("contentHeight").toInt() > pCurrentScrollAreaItem->property("height").toInt()) {
            int contentY = varContentY.toInt();
            //                contentY += pItem->property("height").toInt();
            contentY += 1;
            pCurrentScrollAreaItem->setProperty("contentY",contentY);
            qDebug() << "scroll to :" << contentY;
        } else {
            qWarning() << "No contentY property!" << pCurrentScrollAreaItem;
            return QRect();
        }

        qDebug() << "scroll 1 pixcel";
//        //截图一张
//        QImage imageWindow = grabWindow(target);
//        QString fileName = QString("%1/%2-find-scrollArea.png").arg(findArePath).arg(i, 4, 10, QLatin1Char('0'));
//        bool ok = imageWindow.save(fileName, "PNG");
//        if (!ok) {
//            qWarning() << " Save failed:" << fileName;
//        } else {
//            qDebug() << "Save:" << fileName;
//        }
    }

    //            if (!pItem->isVisible())
    //                continue ;
    //            QVariant varContentY = pItem->property("contentY");
    //             qDebug() << "varContentY:" << varContentY;
    //            if (varContentY.isValid() && pItem->property("contentHeight").toInt() > pItem->property("height").toInt()) {
    //                int contentY = varContentY.toInt();
    ////                contentY += pItem->property("height").toInt();
    //                contentY += 1;
    //                pItem->setProperty("contentY",contentY);
    //                qDebug() << "scroll to :" << contentY;
    //            }

    qDebug() << "FindScrollArea end...";

    //3.分析截图滚动区
//    QString imagePath = "D:/MyGitee/MyQtExamples/MyQtExamples/QMLExamples/build-EpLongScreenShot-Desktop_Qt_6_5_0_MinGW_64_bit-Debug/findArea";
//    QDir dirImage(imagePath);
//    QFileInfoList imgInfoList = dirImage.entryInfoList(QStringList()<<"*.png", QDir::NoDotAndDotDot | QDir::Files);
//    qDebug() << "imgs:" << imgInfoList;
//    QStringList imgAbsFileNameList;
//    for (int i = 0; i < imgInfoList.count(); i++) {
//        qDebug() << "FileName:" << imgInfoList[i].absoluteFilePath();
//        imgAbsFileNameList.append(imgInfoList[i].absoluteFilePath());
//    }

//    rectScrollArea = CImageAlgorithm::findDifference(imgAbsFileNameList);
//    qInfo() << "rectScrollArea:" << rectScrollArea;

    return rectScrollArea;
}

void CLongScreenShot::scrollWindow(QWindow *window, QPointF start, QPointF end)
{
    if (!window) {
        qWarning() << "Invalid target window!";
        return;
    }

    qDebug() << "scrollWindow:" << window << start << end;


//    QTest::mouseMove(window, start.toPoint());
//    QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, start.toPoint());
//    QTest::mouseMove(window, end.toPoint() + QPoint(0,-20));
////    QTest::mouseMove(window, end.toPoint()-QPoint(1,-20));
////    QTest::mouseMove(window, end.toPoint());
//    QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, end.toPoint());




    //方法1
//    QPoint startPos(160, 350);  // 起始位置
//    QPoint endPos(160, 70);    // 终点位置

//    // 发送滑动事件

//    QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, startPos);
//    QTest::mouseMove(window, startPos + QPoint(0,-25));
//    QTest::mouseMove(window, startPos);
//    QTest::mouseMove(window, endPos, 20);
//    QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, endPos, 40);

    QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(160, 350));
    QTest::mouseMove(window, QPoint(160, 320), 20);
    QTest::mouseMove(window, QPoint(160, 319), 40);
    QTest::mouseMove(window, QPoint(160, 318), 60);
    QTest::mouseMove(window, QPoint(160, 317), 80);
    QTest::mouseMove(window, QPoint(160, 316), 90);
    QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(160, 320), 100);

//    QTimer::singleShot(100,this,[=]{
//        QTest::mouseMove(window, startPos + QPoint(0,-25));
//    });

//    QTimer::singleShot(200,this,[=]{
//        QTest::mouseMove(window, startPos);
//    });

//    QTimer::singleShot(300,this,[=]{
//        QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, endPos);
//    });


//    QTimer::singleShot(20,this,[=]{
//        QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, endPos);
//        //    QTest::mouseMove(window, endPos);
//        //    QTest::mouseMove(window, endPos);
//        QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, endPos);

//    });



    //方法2
//#define MOUSE_EVENT(type,x,y,gX,gY) QMouseEvent(type, QPointF(x,y), QPointF(gX,gY),Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)

//    QGuiApplication::sendEvent(window, new MOUSE_EVENT(QEvent::MouseButtonPress,123,192,923,468));
//    QGuiApplication::sendEvent(window, new MOUSE_EVENT(QEvent::MouseMove,123,182,923,458));
//    QGuiApplication::sendEvent(window, new MOUSE_EVENT(QEvent::MouseMove,123,172,923,448));
//    QGuiApplication::sendEvent(window, new MOUSE_EVENT(QEvent::MouseButtonRelease,123,162,923,438));

//#undef MOUSE_EVENT
}

QImage CLongScreenShot::grabWindow(QWindow *target)
{
    QQuickWindow *pQuickWindow = qobject_cast<QQuickWindow *>(target);
    if (pQuickWindow) {
        return pQuickWindow->grabWindow();
    } else {
        qWarning() << "cant grab window!!!" << target;
        return QImage();
    }
}
